using System;
using System.Collections.Generic;
using System.Text;
using da = Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.DataAccess;
using Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.Common.DataSets;
using Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.Common;
using Microsoft.ConnectionEngine.Common;


namespace Microsoft.ConnectionEngine.Registers.Core.ServiceProvider.Business
{
    /// <summary>
    /// Provides Business Logic for Message Type operations, including CRUD.
    /// </summary>
    public class MessageTypeManager
    {

        #region Constructor

        /// <summary>
        /// Default constructor
        /// </summary>
        public MessageTypeManager() { }

        #endregion

        #region Get/search methods

        [Obsolete("Message Type Handlers are loaded from a configuration file by the System Adapter")]
        public static List<MessageTypeHandler> GetMessageTypeHandlers()
        {
            List<MessageTypeHandler> messageHandlerList = new List<MessageTypeHandler>();
            dsMessageTypeHandler ds = da.MessageType.GetMessageTypeHandler();
            foreach (dsMessageTypeHandler.MessageTypeHandlerRow dr in ds.MessageTypeHandler)
            {
                messageHandlerList.Add(
                    new MessageTypeHandler(
                        dr.messageTypeID,
                        dr.assemblyName, 
                        dr.className, 
                        dr.methodName));
            }
            return messageHandlerList;
        }

        /// <summary>
        /// Gets a list of message types based on a search criteria.
        /// </summary>
        /// <param name="messageTypeSearchRequest">An object representation of the search criteria.</param>
        /// <returns>Returns a list of message types that match the search criteria.</returns>
        public static MessageTypesList MessageTypeSearch(MessageTypeSearchRequest messageTypeSearchRequest)
        {
            MessageTypesList messagetypes = new MessageTypesList();
            dsMessageType ds = da.MessageType.MessageTypeSearch(messageTypeSearchRequest.Description, messageTypeSearchRequest.Version, messageTypeSearchRequest.SourceServiceProviderTypeID, messageTypeSearchRequest.DestinationServiceProviderTypeID);

            foreach (dsMessageType.MessageTypeRow dr in ds.MessageType)
            {
                MessageType currentMessageType = new MessageType();
                currentMessageType.MessageTypeID = dr.MessageTypeID;
                currentMessageType.Description = dr.Description;
                currentMessageType.XmlSchema = dr.XmlSchema;
                currentMessageType.Version = dr.Version;
                currentMessageType.ServiceProviderTypeMessageTypeID = Utilities.ConvertNullableInt(dr.ServiceProviderTypeMessageTypeID);
                currentMessageType.SourceDisplayName = dr.SourceDisplayName;
                currentMessageType.DestinationDisplayName = dr.DestinationDisplayName;
                messagetypes.Items.Add(currentMessageType);
            }
            return messagetypes;
        }

        /// <summary>
        /// Gets a specific MessageType by ID
        /// </summary>
        /// <param name="messagetypeid">The ID of the MessageType to retrieve</param>
        /// <returns>A MessageType object representing the requested MessageType</returns>
        public static MessageType MessageTypeSelectItem(string messageTypeID)
        {
            MessageType currentMessageType = new MessageType();
            dvRefData ds = da.MessageType.MessageTypeSelectItem(messageTypeID);
            dvRefData.MessageTypeRow dr = ds.MessageType[0];

            currentMessageType.MessageTypeID = dr.messageTypeID;
            currentMessageType.Description = dr.description;
            currentMessageType.XmlSchema = dr.xmlSchema;
            currentMessageType.Version = dr.version;


            //currentMessageType.ServiceProviderTypes = ServiceProviderTypeMessageTypeSearch(messagetypeid, "").Items;

            return currentMessageType;            
        }

        #endregion

        #region Insert/Update methods
        /// <summary>
        /// Inserts a MessageType
        /// </summary>
        /// <param name="messageType">The MessageType to be inserted</param>
        /// <param name="userID">User Id</param>
        /// <returns>0 - if successful</returns>
        public static string MessageTypeInsert(MessageType messageType, string userID)
        {
            string newMTID = string.Empty;

            //Work Item ID: 1436
            //Modified By: SachinJo
            if (messageType == null)
                return "99";

            if (da.MessageType.MessageTypeExists(messageType.Description) == 0)
            {

                newMTID = da.MessageType.MessageTypeInsert(
                    messageType.Description, messageType.XmlSchema, messageType.Version);
            }

            // return error if insert failed (i.e didn't return a new key)
            //Work Item ID: 1597
            //Modified By: SachinJo
            if (string.IsNullOrEmpty(newMTID)) return "99";

            // set ID to value returned from insert 
            messageType.MessageTypeID = int.Parse(newMTID);
            

            // otherwise, return successful
            return "0";
        }

        /// <summary>
        /// Updates a MessageType
        /// </summary>
        /// <param name="messageType">The MessageType to be updated</param>
        /// <param name="userID">The user that should have the object locked</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string MessageTypeUpdate(MessageType messageType, string userID)
        {
            if (messageType == null)
                return "99";

            // return error if object is not already checked out to provider
            if (!da.MessageType.MessageTypeIsLockedByUser(messageType.MessageTypeID.ToString(), userID)) return "10";

            int result = da.MessageType.MessageTypeExists(messageType.Description);
            if (result == 0 || result == messageType.MessageTypeID)
            {
                // return error if can't update 
                if (!da.MessageType.MessageTypeUpdate(
                    messageType.MessageTypeID.ToString(), messageType.Description, messageType.XmlSchema, messageType.Version))
                {
                    return "99";    // can't update
                }
            }
            else
            {
                return "99";
            }

            // otherwise, return successful
            return "0";
        }
       

        #endregion

        #region Delete methods

        /// <summary>
        /// Deletes a MessageType
        /// </summary>
        /// <param name="messagetypeid">The MessageType to be deleted</param>
        /// <param name="checkoutproviderid">The provider that has the object checked out</param>
        /// <param name="userID">The user that needs to have the object locked</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string MessageTypeDelete(string messageTypeID, string userID)
        {
            // return error if object is not already checked out to provider
            if (!da.MessageType.MessageTypeIsLockedByUser(messageTypeID, userID)) return "10";

            //delete the children:
            //  delete all links in table ServiceProviderTypeMessageType:
            if (!da.ServiceProviderTypeMessageType.ServiceProviderTypeMessageTypeDeleteByMessageTypeID(messageTypeID)) return "99";

            // return error if can't delete messagetypemessagetype children
            //if (!da.PoolMessageType.PoolMessageTypeDeleteByMessageTypeID(messagetypeid)) return "99";
            //TODO: delete from ptMsg table

            // return error if can't delete 
            if (!da.MessageType.MessageTypeDelete(messageTypeID)) return "99";    // can't delete

            // otherwise, return successful
            return "0";
        }

        #endregion

        #region Lock/Unlock methods

        /// <summary>
        /// Checks out a MessageType
        /// </summary>
        /// <param name="messagetypeid">The MessageType to be checked out</param>
        /// <param name="messageTypeID">The MessageType to be locked</param>
        /// <param name="userID">The user that is locking the object</param>
        /// <param name="checkoutproviderid">The provider that is checking the object out</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string MessageTypeLock(string messageTypeID, string userID)
        {
            // return error if object is already checked out
            if (da.MessageType.MessageTypeIsLocked(messageTypeID))
            {
                if (da.MessageType.MessageTypeIsLockedByUser(messageTypeID, userID))
                    return "0";
                else
                    return "9";                
            }
            // return error if check out fails
            if (!da.MessageType.MessageTypeLock(messageTypeID, userID)) return "99";

            // otherwise, return successful
            return "0";
        }


        /// <summary>
        /// Unlocks a MessageType
        /// </summary>
        /// <param name="messagetypeid">The MessageType that is checked out</param>
        /// <param name="messageTypeId">The MessageType that is locked</param>
        /// <param name="checkoutproviderid">The provider that has the object checked out</param>
        /// <param name="userID">The user that has the object locked</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string MessageTypeUnlock(string messageTypeID, string userID)
        {
            // return error if object is not already checked out to provider
            if (!da.MessageType.MessageTypeIsLockedByUser(messageTypeID, userID)) return "10";

            // return error if check in fails
            if (!da.MessageType.MessageTypeUnlock(messageTypeID)) return "99";

            // otherwise, return successful
            return "0";
        }


        /// <summary>
        /// Unlocks all MessageTypes locked out by a specific provider
        /// </summary>
        /// <param name="checkoutproviderid">The specific provider</param>
        /// <returns>A status code ("0" is successful)</returns>
        public static string MessageTypeUnlockAll(string userID)
        {
            // return error if check in fails
            if (!da.MessageType.MessageTypeUnlockAll(userID)) return "99";

            // otherwise, return successful
            return "0";
        }

        
        #endregion


        #region ServiceProviderTypeMessageType methods

        /// <summary>
        /// Gets a list of ServiceProviderTypeMessageType based on a search criteria.
        /// </summary>
        /// <param name="messageTypeID">The messagetypeid to be searched for.</param>
        /// <param name="serviceProviderTypeID">The serviceprovidertypeID to be searched for.</param>
        /// <returns>Returns a list of ServiceProviderTypeMessageType that match the search criteria.</returns>
        public static ServiceProviderTypeMessageTypes ServiceProviderTypeMessageTypeSearch(string messageTypeID, string serviceProviderTypeID)
        {            
            ServiceProviderTypeMessageTypes providerTypes = new ServiceProviderTypeMessageTypes();
            dsServiceProviderTypeMessageType ds =
                da.ServiceProviderTypeMessageType.ServiceProviderTypeMessageTypeSearch(messageTypeID, serviceProviderTypeID);

            foreach (dsServiceProviderTypeMessageType.ServiceProviderTypeMessageTypeRow dr in ds.ServiceProviderTypeMessageType)
            {
                ServiceProviderTypeMessageType currentType = new ServiceProviderTypeMessageType();
                currentType.ServiceProviderTypeMessageTypeID = dr.serviceProviderTypeMessageTypeID;
                currentType.MessageType =
                    new MessageType(dr.messageTypeID, dr.messageTypeDescription, dr.messageTypeXmlSchema, dr.messageTypeVersion);
                currentType.SourceServiceProviderType =
                    new ServiceProviderType(dr.sourceServiceProviderTypeID, dr.sourceServiceProviderTypeDisplayName,
                        dr.sourceServiceProviderTypeCode);
                currentType.DestinationServiceProviderType =
                    new ServiceProviderType(dr.destinationServiceProviderTypeID, dr.destinationServiceProviderTypeDisplayName,
                        dr.destinationServiceProviderTypeCode);
                providerTypes.Items.Add(currentType);
            }
            
           return providerTypes;
        }

        /// <summary>
        /// Adds a ServiceProviderTypes to MessageType link
        /// </summary>
        /// <returns>A status code ("0" is successful)</returns>
        public static string ServiceProviderTypeMessageTypeLinkInsert(ServiceProviderTypeMessageTypeLinks sptMessageTypeLinks)
        {
            string result = "0";
            foreach (ServiceProviderTypeMessageTypeLink sptMessageTypeLink in sptMessageTypeLinks.Items)
            {
                string status = ServiceProviderTypeMessageTypeLinkInsert(sptMessageTypeLink);
                if (status != "0") result = status;
            }
            return result;
        }


        /// <summary>
        /// Adds a ServiceProviderType to MessageType link
        /// </summary>
        /// <returns>A status code ("0" is successful)</returns>
        public static string ServiceProviderTypeMessageTypeLinkInsert(ServiceProviderTypeMessageTypeLink sptMessageTypeLink)            
        {
            // if new row doesn't exist, attempt to insert
            if (!da.ServiceProviderTypeMessageType.ServiceProviderTypeMessageTypeExists(
                sptMessageTypeLink.MessageTypeID.ToString(), sptMessageTypeLink.SourceServiceProviderTypeID.ToString(), 
                sptMessageTypeLink.DestinationServiceProviderTypeID.ToString()))
            {
                // if unable to insert, return error.
                if (!da.ServiceProviderTypeMessageType.ServiceProviderTypeMessageTypeInsert(
                    sptMessageTypeLink.MessageTypeID.ToString(), sptMessageTypeLink.SourceServiceProviderTypeID.ToString(), 
                    sptMessageTypeLink.DestinationServiceProviderTypeID.ToString())) return "99";
            }

            // otherwise, return successful
            return "0";
        }

        /// <summary>
        /// Deletes a ServiceProviderType to MessageType link
        /// </summary>
        /// <returns>A status code ("0" is successful)</returns>
        public static string ServiceProviderTypeMessageTypeDelete(string serviceProviderTypeMessageTypeID,
            string MessageTypeID, string sourceServiceProviderTypeID, string destinationServiceProviderTypeID)
        {
            return ServiceProviderTypeMessageTypeDelete(serviceProviderTypeMessageTypeID);
        }

        /// <summary>
        /// Deletes a ServiceProviderType to MessageType link
        /// </summary>
        /// <returns>A status code ("0" is successful)</returns>
        public static string ServiceProviderTypeMessageTypeDelete(string serviceProviderTypeMessageTypeID)
        {           
            // if unable to update, return error.
            if (!da.ServiceProviderTypeMessageType.ServiceProviderTypeMessageTypeDelete(serviceProviderTypeMessageTypeID)) return "99";

            // otherwise, return successful
            return "0";
        }

       /// <summary>
        /// Deletes a group of ServiceProviderTypeMessageType entries passed as a parameter.
       /// </summary>
       /// <param name="sptMessageTypeLinks">A list of ServiceProviderTypeMessageType to be deleted.</param>
       /// <returns>Returns a string representing the success of the operation.</returns>
        public static string ServiceProviderTypeMessageTypeLinkDelete(ServiceProviderTypeMessageTypeLinks sptMessageTypeLinks)
        {
            //TODO: transaction ?
            string result = "0";
            foreach (ServiceProviderTypeMessageTypeLink sptMessageTypeLink in sptMessageTypeLinks.Items)
            {
                string status = ServiceProviderTypeMessageTypeDelete(sptMessageTypeLink.ServiceProviderTypeMessageTypeID.ToString());
                if (status != "0") result = status;
            }
            // otherwise, return successful
            return result;
        }

        #endregion
    }

}
        
